home *** CD-ROM | disk | FTP | other *** search
- /* This is the BeBox version written by John Fehr.
-
- Due to the changes I've made, this probably doesn't work anymore.
- But it should be straightforward to get this working again.
-
- -- Jeff Tsay */
-
- #include <stdio.h>
- #include <string.h>
- #include <MediaKit.h>
- #include <KernelKit.h>
- #include <Application.h>
- #include <InterfaceKit.h>
-
- #include "args.h"
-
- #define READ_BUFFERS 20
- BLocker lb[READ_BUFFERS];
- char buffers[READ_BUFFERS][4096];
-
- long curwbuf=0;
- long currbuf=0;
- long bebox_ok=1;
-
- DWORD maplay(MPEG_Args *);
-
- int ProcessArgs(int argc,char *argv[],MPEG_Args *);
-
- MPEG_Args ma;
-
- class mpegApp : public BApplication
- {
- private:
- thread_id mpeg_decode_thread;
- thread_id audio_thread;
- long processed_args;
- public:
- mpegApp();
- ~mpegApp();
- virtual void ArgvReceived(int argc,char **argv);
- virtual void ReadyToRun(void);
- };
-
-
-
- long MPEG_Reader_Process(void *data)
- {
- //long retval=(long)start_decode();
- long retval=maplay(&ma);
- bebox_ok=0;
- lb[curwbuf].Unlock();
- fprintf(stderr,"MPEG_Reader_Process: returning %d\n",retval);
- return retval;
- }
-
- long stalled=0;
- double maxtime=0.0;
- double mintime=1000000.0;
- double t=0.0;
-
- bool stream_function(void *arg,char *buffer,long count)
- {
- int tcurrbuf;
- memcpy(buffer,buffers[currbuf],count);
- tcurrbuf=currbuf+1;
- tcurrbuf=(tcurrbuf==READ_BUFFERS)?0:tcurrbuf;
- if (tcurrbuf==curwbuf) stalled++;
- lb[tcurrbuf].Lock();
- lb[currbuf].Unlock();
- currbuf=tcurrbuf;
- if ((!bebox_ok) && currbuf==curwbuf)
- return FALSE;
- return TRUE;
- }
-
- long completion_function(void *arg,long error)
- {
- fprintf(stderr,"completed\n");
- return B_NO_ERROR;
- }
-
- long Audio_Process(void *data)
- {
- BAudioSubscriber *b=(BAudioSubscriber *)data;
- fprintf(stderr,"Entering stream\n");
- b->EnterStream(NULL,TRUE,NULL,stream_function,completion_function,FALSE);
- fprintf(stderr,"Unlocking\n");
- lb[currbuf].Unlock();
- fprintf(stderr,"ReadyToRun::done!\n");
- b->Unsubscribe();
- bebox_ok=0;
- fprintf(stderr,"quiting!\n");
- be_app->PostMessage(B_QUIT_REQUESTED);
- return B_NO_ERROR;
- }
-
-
- int Usage(char *pname)
- {
- fprintf(stderr,"\nusage: %s [-v] [-s] [-l] [-r]"
- "[-f ushort] filename\n"
- " filename filename of a MPEG audio stream or - for stdin\n"
- #ifdef VERBOSE
- " -v verbose mode\n"
- #endif
- " -s write pcm samples to stdout\n"
- " -l decode only the left channel\n"
- " -r decode only the right channel\n"
- #ifdef VERBOSE
- " -c check for filter range violations\n"
- #endif
- " -f ushort use this scalefactor instead of the default value 32768\n\n"
- "@(#) MPEG Audio Player maplay 1.2 "
- "(BeOS DR8.2 version)\n"
- "@(#) Copyright (C) 1993, 1994 Tobias Bading (bading@cs.tu-berlin.de)\n"
- "@(#) Berlin University of Technology\n"
- "@(#) Created: 6/23/94 14:12:46\n"
- "@(#) This program is free software. See the GNU General Public License\n"
- "@(#) in the file COPYING for more details.\n\n"
- ,pname);
- return 0;
- }
-
- int ProcessArgs(int argc,char *argv[],MPEG_Args *ma)
- {
- int i;
- if (argc < 2 || !strncmp (argv[1], "-h", 2))
- {
- return Usage(argv[0]);
- }
- // parse arguments:
- for (i = 1; i < argc; ++i)
- if (argv[i][0] == '-' && argv[i][1])
- switch ((int)argv[i][1])
- {
- case 'v':
- #ifdef VERBOSE
- verbose_mode = TRUE;
- #else
- fprintf(stderr,"maplay: not compiled with VERBOSE.\n");
- #endif
- break;
- case 's':
- ma->stdout_mode = TRUE;
- break;
- case 'l':
- ma->which_channels = left;
- break;
- case 'r':
- ma->which_channels = right;
- break;
- case 'c':
- #ifdef VERBOSE
- ma->filter_check = TRUE;
- #else
- fprintf(stderr,"maplay: not compiled with VERBOSE.\n");
- #endif
- break;
- case 'f':
- if (++i == argc)
- {
- fprintf(stderr,"please specify a new scalefactor after the -f option!\n");
- exit (1);
- }
- ma->use_own_scalefactor = TRUE;
- sscanf (argv[i], "%f", &ma->scalefactor);
- break;
- default:
- return Usage(argv[0]);
- }
- else if (!ma->filename[0])
- strcpy(ma->filename,argv[i]);
- else
- return Usage(argv[0]);
-
- if (!ma->filename[0])
- return Usage(argv[0]);
- if (!(ma->use_speaker || ma->use_headphone || ma->use_line_out))
- ma->use_speaker = TRUE;
-
- if (!strcmp (ma->filename, "-"))
- ma->stream = new Ibitstream (0); // read from stdin
- else
- ma->stream = new Ibitstream (ma->filename); // read from file
-
- ma->MPEGheader = new Header;
- if (!ma->MPEGheader->read_header (ma->stream, &ma->crc))
- {
- fprintf(stderr,"no header found!\n");
- return 0;
- }
- return 1;
- }
-
- DWORD maplay_setup (MPEG_Args *ma)
- {
-
- enum e_channels which_channels = ma->which_c;
-
- e_mode mode;
- e_sample_frequency sample_frequency;
-
- // get info from header of first frame:
- if ((mode = ma->MPEGheader->mode ()) == single_channel)
- which_channels = left;
- sample_frequency = ma->MPEGheader->sample_frequency ();
-
- // create filter(s):
- if (ma->use_own_scalefactor)
- ma->filter1 = new SynthesisFilter (0, ma->scalefactor);
- else
- ma->filter1 = new SynthesisFilter (0);
- if (mode != single_channel && ma->which_channels == both)
- if (ma->use_own_scalefactor)
- ma->filter2 = new SynthesisFilter (1, ma->scalefactor);
- else
- ma->filter2 = new SynthesisFilter (1);
-
- // create buffer:
- if (ma->stdout_mode)
- if (mode == single_channel || which_channels != both)
- ma->buffer = (Obuffer *)new FileObuffer (1);
- else
- ma->buffer = new FileObuffer (2);
- else
- {
- if (mode == single_channel || which_channels != both)
- ma->buffer = new BEOSObuffer (1,ma->MPEGheader); // mono
- else
- ma->buffer = new BEOSObuffer (2,ma->MPEGheader); // stereo
- }
-
- #ifdef VERBOSE
- if (verbose_mode)
- {
- // print informations about the stream
- char *name = strrchr (filename, '/');
- if (name)
- ++name;
- else
- name = filename;
- fprintf(stderr,"%s is a layer %s %s MPEG audio stream with",
- name,ma->MPEGheader->layer_string(),ma->MPEGheader->mode_string());
- if (!ma->MPEGheader->checksums ())
- fprintf(stderr,"out");
- fprintf(stderr, " checksums.\nThe sample frequency is %s"
- " at a bitrate of %s\nThis stream is ",
- ma->MPEGheader->sample_frequency_string(),ma->MPEGheader->bitrate_string());
- if (ma->MPEGheader->original ())
- fprintf(stderr,"an original");
- else
- fprintf(stderr,"a copy");
- fprintf(stderr," and is ");
- if (!ma->MPEGheader->copyright ())
- fprintf(stderr,"not ");
- fprintf(stderr, "copyright protected.\n");
- }
- #endif
- return 1;
- }
-
-
-
- void mpegApp::ArgvReceived(int argc,char **argv)
- {
- fprintf(stderr,"ArgsReceived()\n");
- if (!ProcessArgs(argc,argv,&ma))
- {
- processed_args=0;
- be_app->PostMessage(new BMessage(B_QUIT_REQUESTED));
- return;
- }
- printf("Running maplay_setup\n");
- maplay_setup(&ma);
- // old_main(argc,argv);
- processed_args=1;
- }
-
- void mpegApp::ReadyToRun(void)
- {
- fprintf(stderr,"ReadyToRun(): processed_args=%d\n",processed_args);
- BAudioSubscriber *b;
- long thread_return;
-
- if (!processed_args)
- {
- fprintf(stderr,"Args not processed.\n");
- bebox_ok=0;
- return;
- }
- // lock buffer[0] for the file reader (decoder) thread
- lb[0].Lock();
-
- printf("Creating mpeg_decode_thread\n");
- if (resume_thread(
- mpeg_decode_thread=spawn_thread(MPEG_Reader_Process,
- "READ Task",B_URGENT_DISPLAY_PRIORITY,/*B_NORMAL_PRIORITY,*/NULL))<B_NO_ERROR)
- {
- fprintf(stderr,"Failed to spawn or resume DecodeProcess.\n");
- bebox_ok=0;
- return;
- }
-
- // lock buffer 0 for the write task
- lb[0].Lock();
-
- // snooze(3*1000000);
-
- fprintf(stderr,"spawned 'READ Task'\n");
- // once the first buffer is read, lb[0] gets unlocked, so lock it for
- if (!(b=new BAudioSubscriber("MPEG Audio Out")))
- {
- fprintf(stderr,"Error creating BAudioSubscriber.\n");
- bebox_ok=0;
- lb[currbuf].Unlock();
- wait_for_thread(mpeg_decode_thread,&thread_return);
- exit(0);
- }
- b->EnableDevice(B_DAC_OUT,TRUE);
- b->SetVolume(B_DAC_OUT,1.0,1.0);
- b->SetDACSampleInfo(2,2,B_BIG_ENDIAN,B_LINEAR_SAMPLES);
- b->SetSamplingRate(44100);
- if (b->Subscribe(B_DAC_STREAM,B_SHARED_SUBSCRIBER_ID,FALSE)!=B_NO_ERROR)
- {
- fprintf(stderr,"Error subscribing to B_DAC_STREAM as B_SHARED_SUBSCRIBER_ID.\n");
- delete b;
- bebox_ok=0;
- lb[currbuf].Unlock();
- wait_for_thread(mpeg_decode_thread,&thread_return);
- exit(0);
- }
- if (resume_thread(
- audio_thread=spawn_thread(Audio_Process,
- "Audio Task",B_NORMAL_PRIORITY,(void *)b))<B_NO_ERROR)
- {
- fprintf(stderr,"Failed to spawn or resume Audio_Process.\n");
- bebox_ok=0;
- return;
- }
- }
-
- class mpegWindow : public BWindow
- {
- public:
- mpegWindow(BRect frame,char *title,window_type type,ulong flags);
- virtual bool QuitRequested();
- };
-
- bool mpegWindow::QuitRequested()
- {
- be_app->PostMessage(new BMessage(B_QUIT_REQUESTED));
- return TRUE;
- }
-
- mpegWindow::mpegWindow(BRect frame,char *title,window_type type,ulong flags)
- : BWindow(frame,title,type,flags)
- {
- }
-
- mpegApp::mpegApp(): BApplication('mpga')
- {
- mpeg_decode_thread=0;
- audio_thread=0;
- curwbuf=0;
- currbuf=0;
- bebox_ok=1;
- processed_args=0;
-
- fprintf(stderr,"mpegApp()\n");
-
- mpegWindow *bw=new mpegWindow(BRect(91,102,230,140), "mpeg",
- B_TITLED_WINDOW,B_NOT_RESIZABLE);
- BButton *bb=new BButton(BRect(25,9,112,20),"Stop","Stop",
- new BMessage(B_QUIT_REQUESTED),B_FOLLOW_NONE,B_WILL_DRAW);
- bw->AddChild(bb);
- bw->Show();
-
- }
-
- mpegApp::~mpegApp()
- {
- long thread_return;
- bebox_ok=0;
- printf("set ok to 0\n");
- if (mpeg_decode_thread) wait_for_thread(mpeg_decode_thread,&thread_return);
- if (audio_thread) wait_for_thread(audio_thread,&thread_return);
- printf("Thread returned\n");
- // printf("Deleted\n");
- }
-
-
- static long c=0;
-
- long curbpos=0;
-
- long write_to_buffer(char *buf,int length)
- {
- char *buffer=buffers[curwbuf];
- long tcurwbuf;
- long retlen=length;
-
- //printf("write %d, curbpos=%d,curwbuf=%d,currbuf=%d\n",length,curbpos,curwbuf,currbuf);
- // fill in as many full buffers as we can
- while (curbpos+length>=4096)
- {
- memcpy(buffer+curbpos,buf,4096-curbpos);
- length-=(4096-curbpos);
- buf+=(4096-curbpos);
- curbpos=0;
-
- // release the hounds! er.. the buffer
- tcurwbuf=curwbuf+1;
- tcurwbuf=(tcurwbuf==READ_BUFFERS)?0:tcurwbuf;
- lb[tcurwbuf].Lock();
- lb[curwbuf].Unlock();
- curwbuf=tcurwbuf;
-
- // find the next output buffer.
- buffer=buffers[curwbuf];
- }
-
- // put what's left in the buffer
- memcpy(buffer+curbpos,buf,length);
- curbpos+=length;
- // printf("curbpos=%d,length=%d\n",curbpos,length);
-
- return retlen;
- }
-
- main(int argc,char *argv[])
- {
- if (argc==1)
- {
- return Usage(argv[0]);
- }
- mpegApp *ma=new mpegApp();
- ma->Run();
- delete ma;
- fprintf(stderr,"stalled=%d\n",stalled);
- return 0;
- }
-